"use strict"
/// <reference path="../../index.d.ts" />
const Controller = require("egg").Controller
const {sendStat, ipV4toInt, getIP, intToIp, getToDay, todayRemaining} = require("../extend/helper")
let hasOwnProperty = Object.prototype.hasOwnProperty
let gameConfig = require("../../config/game")
//后台用户路由
class UserController extends Controller {

	constructor(ctx) {
		super(ctx)
		this.Application = this.app.model.Application
		this.ApplicationUser = this.app.model.ApplicationUser
		this.Module = this.app.model.Module
		this.Address = this.app.model.Address
		// this.constant = this.config.constant
		this.UserEmpireStore = this.app.model.Game.UserEmpireStore
		this.AdCount = this.app.model.AdCount
		this.redisHelp = this.service.db
	}

	async list() {
		let {ctx, ApplicationUser, config, service} = this
		ctx.validate({
			aid: "numstr",
			mid: {
				required: false,
				type: "numstr"
			},
			nickname: {
				required: false,
				allowEmpty: false,
				type: "string"
			},
			oid: {
				required: false,
				allowEmpty: false,
				type: "pintstr"
			}
		}, ctx.query)
		var query = {
			aid: Number(ctx.query.aid),
			mid: hasOwnProperty.call(ctx.query, "mid") ? Number(ctx.query.mid) : false,
			oid: ctx.query.oid,
			nickname: ctx.query.nickname,
		}

		if (query.mid == false) {// 小程序用户
			let dbQuery = {
				limit: ctx.pageListNum,
				offset: ctx.startPage,
				where: {
					aid: query.aid
				},
				order: [["create_at", "desc"]],
			}
			if (query.nickname) {
				dbQuery = {
					where: {
						aid: query.aid,
						nickname: {
							$like: `%${query.nickname}%`
						}
					},
					order: [["create_at", "desc"]],
				}
			}
			if (query.oid) {
				dbQuery = {
					where: {
						aid: query.aid,
						id: query.oid
					},
					order: [["create_at", "desc"]],
				}
			}
			let dat = await ApplicationUser.findAndCountAll(dbQuery)
			ctx.body = sendStat(config.constant.NORMAL, dat.rows)
			ctx.body.count = dat.count
		} else {
			//模块用户
			let unionStat = await service.application.getModuleUnionType(query.mid)
			if (unionStat.stat == -1) {
				ctx.body = sendStat(config.constant.ERROR_DB_MISS)
				return
			}
			let queryObj = await service.moduleApplicat.getAppUser(query.aid, query.mid)

			this.ctx.body = sendStat(config.constant.NORMAL, queryObj.users)
			this.ctx.body.count = queryObj.count
		}
		/**
		 * @type {Object[]}
		 */
		let users = ctx.body.d
		var ips = users.map((v) => {
			return v.ip
		})
		let ipMap = await ctx.service.server.getIps(ips)
		users.forEach((v, index) => {
			let val = v.dataValues
			if (!hasOwnProperty.call(ipMap, v.ip)) {
				this.app.redis.publish("ip", JSON.stringify({ip: intToIp(v.ip)}))
			}
			val.address = ipMap[v.ip] || ""
			users[index] = val
			return val
		})
	}
	/* 
	个人用户 */
	async getGameUsers() {
		let {ctx, config, service} = this
		ctx.validate({
			oids: "arraystr",
			aid: "numstr",
			nickname: {
				required: false,
				type: "string"
			}
		}, ctx.query)
		let oids = JSON.parse(ctx.query.oids)
		let gameUserRes = await service.moduleApplicat.getEmpireUser({aid: ctx.query.aid, oids, nickname: ctx.query.nickname})
		ctx.body = sendStat(config.constant.NORMAL, gameUserRes.rows || [])
		ctx.body.count = gameUserRes.count
		let users = ctx.body.d
		var ips = users.map((v) => {
			return v.ip
		})
		let ipMap = await ctx.service.server.getIps(ips)
		users.forEach((v, index) => {
			let val = v.dataValues
			if (!hasOwnProperty.call(ipMap, v.ip)) {
				this.app.redis.publish("ip", JSON.stringify({ip: intToIp(v.ip)}))
			}
			val.address = ipMap[v.ip] || ""
			users[index] = val
			return val
		})
	}
	//其余的一些信息
	async getUserGameInfo() {
		let {ctx, config, service} = this
		ctx.validate({oid: "pintstr", aid: "string"}, ctx.query)
		let oid = ctx.query.oid
		let user = await service.empire.getGameUser(oid)
		if (!user) {
			return ctx.body = sendStat(config.constant.EMPIRE_USER_MISS)
		}
		// let {sell_count} = user
		let apprentices = await service.empire.getApprentice(oid)
		let userStoreNum = await this.UserEmpireStore.count({
			where: {
				oid: oid,
				sales_round: user.sell_count
			}
		})
		ctx.body = sendStat(config.constant.NORMAL, {...user.dataValues, apprentices, userStoreNum})
	}

	async updateUserInfo() {
		let {ctx} = this
		let body = ctx.request.body
		//验证
		ctx.logger.warn(JSON.stringify(body))
		ctx.validate({
			avatar: {
				allowEmpty: true,
				type: "string"
			}, nickName: "string", gender: "numstr",
			city: {
				allowEmpty: true,
				type: "string"
			}, province: {
				allowEmpty: true,
				type: "string"
			}, country: {
				allowEmpty: true,
				type: "string"
			}, language: "string"
		}, body)
		let {province, country, language, city} = body
		let obj = {province, country, language, city}

		obj.sex = body.gender == 1 ? "1" : body.gender == 2 ? "0" : null
		obj.nickname = body.nickName
		obj.headimg_url = body.avatar
		obj.last_login = Date.now()
		obj.stat = 1
		let updateStat = await this.service.moduleApplicat.updateUserInfoProm(obj)
		if (updateStat && updateStat[0])
			ctx.body = sendStat(this.config.constant.NORMAL, "更新成功")
		else {
			ctx.body = sendStat(this.config.constant.ERROR_SQL_UPDATE)
		}
	}

	async setChannel() {
		let {ctx} = this
		let body = ctx.request.body
		let channel = await this.app.cache.channel

		let channelIds = channel.map(v => {
			return (v.id).toString()
		})
		ctx.validate({channelId: channelIds}, body)

		let updateStat = await this.service.moduleApplicat.updateUserInfoProm({channel: body.channelId, last_login: Date.now()})
		if (updateStat && updateStat[0])
			ctx.body = sendStat(this.config.constant.NORMAL, "更新成功")
		else {
			ctx.body = sendStat(this.config.constant.ERROR_SQL_UPDATE)
		}
	}
	/**
	 * 获取小程序的用户信息
	 */
	async getUserInfo() {
		let {ctx, config} = this
		let userData = await this.service.moduleApplicat.getUserInfo()
		if (userData == null) {
			ctx.body = sendStat(config.constant.ERROR_PERMISS_NOT_ALLOWED, {msg: "创建用户失败/未授权"})
			ctx.logger.error("查无此人/ 获取用户数据")
			return
		}
		let {province, country, language, city} = userData
		let obj = {province, country, language, city}
		obj.gender = userData.sex == 1 ? "1" : userData.sex === 0 ? "2" : null
		obj.nickName = userData.nickname
		obj.avatar = userData.headimg_url || gameConfig.defaultHead
		obj.ip = this.ctx.get("X-Real-IP")

		let intIp = obj.ip && ipV4toInt(obj.ip)
		if (obj.ip && intIp) {
			let address
			let v = await this.redisHelp.getRedisObj("ip." + intIp)
			if (v) {
				try {
					obj.country = address.country
					obj.city = address.city
					obj.province = address.province
				} catch (error) {
					ctx.logger.warn(obj.ip)
				}
			} else {
				address = await this.Address.findById(intIp)
				if (address) {
					obj.country = address.country
					obj.city = address.city
					obj.province = address.region
				} else {
					try {
						let data = await getIP(obj.ip)
						if (data) {
							obj.country = data[0]
							obj.province = data[1]
							obj.city = data[2]
							this.app.redis.publish("ip", JSON.stringify({ip: obj.ip}))
						}
					} catch (error) {
						ctx.logger.error(error)
					}
				}
			}
			if (obj.ip && userData.ip != intIp) {
				this.ApplicationUser.update({ip: intIp}, {
					where: {
						id: this.ctx.userInfo.oid
					}
				})
			}
		}

		ctx.body = sendStat(config.constant.NORMAL, obj)
	}

	async addAdClick() {
		let that = this
		let oid = this.ctx.userInfo.oid
		this.ctx.logger.warn("adcount#click" + oid)
		await this.service.db.getSet("adcount##" + this.ctx.userInfo.oid, {
			expire: todayRemaining(),
			noExist: async () => {
				let adcount = await that.AdCount.findOne({
					where: {
						oid,
						date: Date.now()
					}
				})
				if (adcount)
					return adcount.dataValues
				else {
					return {date: Date.now(), apprentice: [], adClick: 0, oid}
				}
			},
			deal: async (obj) => {
				obj.date = Date.now()
				obj.adClick = obj.adClick || 0
				obj.adClick++
				await this.AdCount.upsert(obj, {fields: ["adClick"], })
				return obj
			}
		})
		this.ctx.body = sendStat(this.config.constant.NORMAL)
	}
}
// let errorCount = 0
module.exports = UserController
